package pessoal.cliente;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import pessoal.Endereco;
import pessoal.Pessoa;
import pessoal.RepositorioPessoaBDR;
import pessoal.cliente.exception.ClienteExistenteException;
import pessoal.cliente.exception.ClienteInvalidoException;
import pessoal.funcionario.RepositorioFuncionariosBDR;
import util.CampoObrigatorioException;
import util.Conexao;
import util.ErroAcessoRepositorioException;

public class RepositorioClientesBDR extends RepositorioPessoaBDR implements IRepositorioClientes {
	
	
	
	private static final String UPDATE_CLIENTE = "UPDATE cliente SET desconto = ?  WHERE cpf_cliente = ?";
		
	private static final String INSERT_CLIENTE="INSERT INTO cliente (cpf_cliente,desconto) VALUES (?,?)";
		
	private static final String CONSULTA_CLIENTE = "SELECT * FROM pessoa INNER " +
			"JOIN cliente ON cpf = cpf_cliente WHERE cpf_cliente = ?";
	
	private static final String DELETE_CLIENTE = "DELETE FROM cliente WHERE cpf_cliente = ?";
	
	private static final String CONSULTA_CLIENTE_LISTAR = "SELECT * FROM pessoa INNER " +
	"JOIN cliente ON cpf = cpf_cliente";
	
	private static final String CONSULTA_CLIENTE_EXISTE = "SELECT * FROM cliente " +
			"WHERE cpf_cliente = ?";
	
	private static final String CONSULTA_CLIENTE_PARA_EXCLUSAO = "SELECT * FROM cliente WHERE cpf_cliente = ?";

		
	public void atualizarClienteFiel(ClienteFiel clienteFiel) 
	throws ClienteInvalidoException, ErroAcessoRepositorioException {
		Connection con = Conexao.getConexao();
		PreparedStatement pstmt = null;
		try {
			pstmt = con.prepareStatement(UPDATE_CLIENTE);
			pstmt.setDouble(1, clienteFiel.getDesconto());
			pstmt.setString(2, clienteFiel.getCpf());
			int rows = pstmt.executeUpdate();
			if (rows <= 0 ){
				throw new ClienteInvalidoException(clienteFiel.getCpf());
 			}
			Endereco end = new Endereco (clienteFiel.getEndereco().getRua(),clienteFiel.getEndereco().getNumero(),clienteFiel.getEndereco().getComplemento()
					,clienteFiel.getEndereco().getBairro(),clienteFiel.getEndereco().getCidade(),clienteFiel.getEndereco().getCep(),clienteFiel.getEndereco().getUf());
			
			Pessoa pessoa = new Pessoa(clienteFiel.getNome(),clienteFiel.getRg(),clienteFiel.getCpf(),end);
			super.alterarPessoa(pessoa);
		} catch (SQLException e) {
			throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD,
					e,
					e.getErrorCode());
		} finally{
			Conexao.fechaRecursos(con,pstmt,null);
		}
	}

	/*
	 * Insere em pessoa e depois insere em funcionario
	 * 
	 */
	public void inserirClienteFiel(ClienteFiel clienteFiel)
	throws ClienteExistenteException, ErroAcessoRepositorioException,
	CampoObrigatorioException {
		Endereco end = new Endereco (clienteFiel.getEndereco().getRua(),clienteFiel.getEndereco().getNumero(),clienteFiel.getEndereco().getComplemento()
				,clienteFiel.getEndereco().getBairro(),clienteFiel.getEndereco().getCidade(),clienteFiel.getEndereco().getCep(),clienteFiel.getEndereco().getUf());
		
		Pessoa pessoa = new Pessoa(clienteFiel.getNome(),clienteFiel.getRg(),clienteFiel.getCpf(),end);
		if(clienteFiel.getCpf()!=null && clienteFiel.getCpf()!="" && clienteFiel.getNome()!=null
				&& clienteFiel.getNome()!="" && clienteFiel.getRg()!=null 
				&& clienteFiel.getRg()!=""){
			Connection con = null;
			PreparedStatement pstmt = null;
			try {
				super.inserePessoa(pessoa);
				if(!existeCliente(clienteFiel.getCpf())){
					con = Conexao.getConexao();
					pstmt=con.prepareStatement(INSERT_CLIENTE);
					pstmt.setString(1, clienteFiel.getCpf());
					pstmt.setDouble(2, clienteFiel.getDesconto());
					pstmt.executeUpdate();
				}else{
					throw new ClienteExistenteException(clienteFiel.getCpf());
				}
			} catch (SQLException e) {
				throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD,
						e,
						e.getErrorCode());
			}finally{
				Conexao.fechaRecursos(con,pstmt,null);
			}
		}else{
			throw new CampoObrigatorioException("CPF, Nome e RG.");
		}
	}
	
	
	public ClienteFiel consultarClienteFiel(String cpf)	
	throws ClienteInvalidoException, ErroAcessoRepositorioException{
		ClienteFiel clienteFiel = null;
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		con = Conexao.getConexao();
		try {
			pstmt=con.prepareStatement(CONSULTA_CLIENTE);
			pstmt.setString(1, cpf);
			rs=pstmt.executeQuery();
			if(rs.next()){
				String nome = rs.getString("nome");
				String rg = rs.getString("rg");
				double desconto = rs.getDouble("desconto");
				String rua = rs.getString("rua");
				String numero = rs.getString("numero");
				String complemento = rs.getString("complemento");
				String bairro = rs.getString("bairro");
				String cidade = rs.getString("cidade");
				String cep = rs.getString("cep");
				String uf = rs.getString("uf");
				clienteFiel = 
					new ClienteFiel(cpf,nome,rg,new Endereco(rua,numero,complemento,bairro,cidade,cep,uf),desconto);
			}else{
				throw new ClienteInvalidoException(cpf);
			}
		} catch (SQLException e) {
			throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD,
					e,
					e.getErrorCode());
		}finally{
			Conexao.fechaRecursos(con,pstmt,rs);
		}
		return clienteFiel;
	}


	/*O excluir exclui de cliente mas nao exclui de pessoa caso esse 
	 * cliente tb seja um func. se esse cliente nao for
	 * tb func ele exclui das duas.
	 *  
	 * */
	public void excluirClienteFiel(String cpf) 
	throws ClienteInvalidoException, ErroAcessoRepositorioException {
		PreparedStatement pstmt = null;
		Connection con = null;
		if(existeCliente(cpf)){
			try {
				con = Conexao.getConexao();
				pstmt = con.prepareStatement(DELETE_CLIENTE);
				pstmt.setString(1, cpf);
				pstmt.executeUpdate();
				RepositorioFuncionariosBDR repFunc = new RepositorioFuncionariosBDR();
				if(!repFunc.existeFuncionario(cpf)){
					super.excluirPessoa(cpf);
				}
			} catch (SQLException e) {
				throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD,
						e,
						e.getErrorCode());
			}finally{
				Conexao.fechaRecursos(con,pstmt,null);
			}
		}else{
			throw new ClienteInvalidoException(cpf);
		}
	}
	
	public boolean existeCliente(String cpf) throws ErroAcessoRepositorioException {
		Connection con = null;
		PreparedStatement pstmt = null;
		con = Conexao.getConexao();
		ResultSet rs = null;
		try {
			pstmt=con.prepareStatement(CONSULTA_CLIENTE_EXISTE);
			pstmt.setString(1, cpf);
			rs = pstmt.executeQuery();
			if(rs.next()){
				String qtdLinhas = rs.getString("cpf_cliente");
				return (qtdLinhas != null);
			}
		} catch (SQLException e) {
			throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD,
					e,
					e.getErrorCode());
		}finally{
			Conexao.fechaRecursos(con,pstmt,rs);
		}
		
		return false;
	}
	
	

	public List<ClienteFiel> listarClientes() throws ErroAcessoRepositorioException{
		PreparedStatement pstmt = null;
		Connection con = null;
		ResultSet rs = null;
		ArrayList<ClienteFiel> clientes = new ArrayList<ClienteFiel>();
		con = Conexao.getConexao();
		try {
			pstmt = con.prepareStatement(CONSULTA_CLIENTE_LISTAR);
			rs = pstmt.executeQuery();
			while(rs.next()){
				String cpf = rs.getString("cpf");
				String nome = rs.getString("nome");
				String rg = rs.getString("rg");
				double desconto = rs.getDouble("desconto");
				String rua = rs.getString("rua");
				String numero = rs.getString("numero");
				String complemento = rs.getString("complemento");
				String bairro = rs.getString("bairro");
				String cidade = rs.getString("cidade");
				String cep = rs.getString("cep");
				String uf = rs.getString("uf");
				Endereco end = 
					new Endereco(rua,numero,complemento,bairro,cidade,cep,uf);
				ClienteFiel cliente = 
					new ClienteFiel(cpf,nome,rg,end,desconto);
				clientes.add(cliente);
			}
		} catch (SQLException e) {
			throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD,
					e,
					e.getErrorCode());
		}finally{
			Conexao.fechaRecursos(con,pstmt,rs);
		}
		return clientes;
	}
	
	
}
